package com.audaque.springboot.foshanupload.core.config;

import com.audaque.springboot.foshanupload.core.handler.AsyncUncaughtExceptionHandlerImpl;
import com.audaque.springboot.foshanupload.core.properties.SystemPropertiesDynamic;
import lombok.extern.slf4j.Slf4j;
import org.springframework.aop.interceptor.AsyncUncaughtExceptionHandler;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

/**
 * @author zgb
 * @desc ...
 * @date 2021-05-24 12:18:24
 */
@Slf4j
@EnableAsync//支持异步, @Async嵌套调用时，外层生效，里层不生效
@Configuration
public class AsyncAnnoConfig extends AsyncConfigurerSupport {

    @Autowired
    private AsyncUncaughtExceptionHandlerImpl asyncUncaughtExceptionHandlerImpl;


    @Autowired
    private ThreadPoolTaskExecutor threadPoolTaskExecutor;

    /**
     * 对没有被捕获的异常进行处理 。也就是说，如果在子线程中产生了异常，且没有被捕获的情况下，异常会被 UncaughtExceptionHandler 进行处理。
     * 线程是一个操作系统层面的概念，java层面的Thread类，仅仅是对线程的一个封装，在Thread类中大部分方法都是native的，所以Thread抛出的异常，其实是系统级别线程抛出的异常，这个异常，java语言层面是无法捕获的。
     * 当一个线程由于未捕获的异常，将要终止时，jvm会捕获到这个异常，然后按照一定的规则找到一个处理该异常的 UncaughtExceptionHandler，并把产生异常的thread和异常实例，作为参数来调用 UncaughtExceptionHandler中的uncaughtException方法，来完成异常的处理。
     */
    @Bean
    public AsyncUncaughtExceptionHandlerImpl asyncUncaughtExceptionHandlerImpl() {
        return new AsyncUncaughtExceptionHandlerImpl();
    }

    @Bean
    public SystemPropertiesDynamic systemPropertiesDynamic() {
        int i = Runtime.getRuntime().availableProcessors();//获取逻辑核心数，如6核心12线程，那么返回的是12
        log.debug("i:" + i);
        SystemPropertiesDynamic systemPropertiesDynamic = new SystemPropertiesDynamic();
        systemPropertiesDynamic.setAvailableProcessors(i);
        return systemPropertiesDynamic;
    }

    @Override
    public ThreadPoolTaskExecutor getAsyncExecutor() {
        return threadPoolTaskExecutor;
    }

    @Override
    public AsyncUncaughtExceptionHandler getAsyncUncaughtExceptionHandler() {
        return asyncUncaughtExceptionHandlerImpl;
    }

}
